<?php
defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once($CFG->dirroot . '/question/type/preg/authoring_tools/preg_explaining_graph_misc.php');
require_once($CFG->dirroot . '/question/type/preg/tests/tool_explaining_graph_test.php');
require_once($CFG->dirroot . '/question/type/preg/preg_graph_to_tree_functions.php');

class qtype_preg_graph_to_tree_tests extends PHPUnit_Framework_TestCase {

    public function test_take_parameter_from_str() {
        
        $resultfunction = take_parameter_from_str('id="explaining_graph";', 'id');
        $this->assertTrue($resultfunction == 'explaining_graph', 'Failed with test_take_parameter_from_str - in begining of line: resultfunction != \'explaining_graph\'');

        // -----------------------------------------------------------------------------

        $resultfunction = take_parameter_from_str('tooltip="";', 'tooltip');
        $this->assertTrue($resultfunction == '', 'Failed with test_take_parameter_from_str - empty substring: resultfunction != \'\'');

        // -----------------------------------------------------------------------------

        $resultfunction = take_parameter_from_str('"nd13" [shape=point, id="graphid_13",color=black, style=solid, label="", fillcolor=white,tooltip=""];', 'shape');
        $this->assertTrue($resultfunction == 'point', 'Failed with test_take_parameter_from_str - after bracket: resultfunction != \'point\'');

        // -----------------------------------------------------------------------------

        $resultfunction = take_parameter_from_str('"nd13" [shape=point, id="graphid_13",color=black, style=solid, label="", fillcolor=white,tooltip=""];', 'tooltip');
        $this->assertTrue($resultfunction == '', 'Failed with test_take_parameter_from_str - before bracket: resultfunction != \'\'');

        // -----------------------------------------------------------------------------

        $resultfunction = take_parameter_from_str('"nd7" -> "nd3_1_1"[id="graphid_9", label="", arrowhead="normal", color="black", tooltip=""];', 'arrowhead');
        $this->assertTrue($resultfunction == 'normal', 'Failed with test_take_parameter_from_str - inside brackets: resultfunction != \'normal\'');

        // -----------------------------------------------------------------------------

        $resultfunction = take_parameter_from_str('"nd8" [shape=box, id="graphid_8", color=purple, style=filled, label="end", fillcolor=purple,tooltip="end"];', 'color');
        $this->assertTrue($resultfunction == 'purple', 'Failed with test_take_parameter_from_str - similar parameter: resultfunction != \'purple\'');
    }

    public function test_add_node_of_graph() {
        $etalonnodeofgraph = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', 'graphid_6_7_7', 'solid', 'white');

        $resultnodeofgraph = add_node_of_graph('"nd6_7_7" [shape=ellipse, id="graphid_6_7_7", fillcolor=white, style=solid, label="b", color=black,tooltip="b"];');

        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($etalonnodeofgraph, $resultnodeofgraph), 'Failed with test_add_node_of_graph: the resulting node of graph is not equal to the reference node of graph!');
    }

    public function test_add_node_of_graph_record_not_invert() {
        $etalonnodeofgraph = new qtype_preg_explaining_graph_tool_node(array('0', 'from a to z', 'from 1 to 1'), 'record', 'black', 'graphid_3_1_9', 'solid', 'white');
        $etalonnodeofgraph->invert = false;

        $resultnodeofgraph = add_node_of_graph('"nd3_1_9" [shape=record, color=black,id="graphid_3_1_9", label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4"><TR><TD COLSPAN="3"><font face="Arial">Any character from</font></TD></TR><TR><TD>0</TD><TD>from a to z</TD><TD>from 1 to 1</TD></TR></TABLE>>, fillcolor=white,tooltip="character class"];');

        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($etalonnodeofgraph, $resultnodeofgraph), 'Failed with test_add_node_of_graph_record_not_invert: the resulting node of graph is not equal to the reference node of graph!');
    }

    public function test_add_node_of_graph_record_invert() {
        $etalonnodeofgraph = new qtype_preg_explaining_graph_tool_node(array('0', 'from a to z', 'from 1 to 1'), 'record', 'black', 'graphid_3_1_10', 'solid', 'white');
        $etalonnodeofgraph->invert = true;

        $resultnodeofgraph = add_node_of_graph('"nd3_1_10" [shape=record, color=black,id="graphid_3_1_10", label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4"><TR><TD COLSPAN="3"><font face="Arial">Any character except</font></TD></TR><TR><TD>0</TD><TD>from a to z</TD><TD>from 1 to 1</TD></TR></TABLE>>, fillcolor=white,tooltip="character class"];');

        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($etalonnodeofgraph, $resultnodeofgraph), 'Failed with test_add_node_of_graph_record_invert: the resulting node of graph is not equal to the reference node of graph!');
    }

    public function test_analysis_subraph_digraph_without_subgraphs() {
        $digraph = array('digraph "explaining graph" {',
            'tooltip="";',
            'id="explaining_graph";',
            'compound=true;',
            'rankdir = LR;',
            '',
            '"nd2_0_1" [shape=ellipse, id="graphid_2_0_1", color=black, style=solid, label="ab", fillcolor=white,tooltip="ab"];',
            '"nd3" [shape=box, id="graphid_3", color=purple, style=filled, label="begin", fillcolor=purple,tooltip="begin"];',
            '"nd4" [shape=box, id="graphid_4", color=purple, style=filled, label="end", fillcolor=purple,tooltip="end"];',
            '"nd3" -> "nd2_0_1"[id="graphid_5", label="", arrowhead="normal", color="black", tooltip="", ]',
            '"nd2_0_1" -> "nd4"[id="graphid_6", label="", arrowhead="normal", color="black", tooltip="", ]',
            '}');

        $etalon = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('ab'), 'ellipse', 'black', null, 'graphid_2_0_1');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', null, 'graphid_3');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', null, 'graphid_4');
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->nodes[1], $etalon->nodes[0], $etalon);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->nodes[0], $etalon->nodes[2], $etalon);

        $pos = 0;

        $resultgraph = analysis_subgraph($digraph, $pos);

        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_graphs($resultgraph, $etalon), 'Failed with test_analysis_subgraph: digraph without subgraphs!');
    }

    public function test_analysis_subgraph_digraph_with_one_subgraph() {
        $digraph = array('digraph "explaining graph" {',
            'tooltip="";',
            'id="explaining_graph";',
            'compound=true;',
            'rankdir = LR;',
            '',
            '"nd3" [shape=box, id="graphid_3", color=purple, style=filled, label="begin", fillcolor=purple,tooltip="begin"];',
            '"nd4" [shape=box, id="graphid_4", color=purple, style=filled, label="end", fillcolor=purple,tooltip="end"];',
            'subgraph "cluster_1_0_1" {style=dotted;color=black;bgcolor=white;label="repeated any number of times";id="graphid_1_0_1";tooltip="quantifier";',
            '"nd2_0_0" [shape=ellipse, id="graphid_2_0_0",color=black, style=solid, label="a", fillcolor=white,tooltip="a"];',
            '}',
            '"nd3" -> "nd2_0_0"[id="graphid_5", label="", arrowhead="normal", color="black", tooltip="", ]',
            '"nd2_0_0" -> "nd4"[id="graphid_6", label="", arrowhead="normal", color="black", tooltip="", ]',
            '}');

        $etalon = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $etalon->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('repeated any number of times', 'graphid_1_0_1');
        $etalon->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', null, 'graphid_2_0_0');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', null, 'graphid_3');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', null, 'graphid_4');
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->nodes[0], $etalon->subgraphs[0]->nodes[0], $etalon);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->subgraphs[0]->nodes[0], $etalon->nodes[1], $etalon);

        $pos = 0;

        $resultgraph = analysis_subgraph($digraph, $pos);

        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_graphs($resultgraph, $etalon), 'Failed with test_analysis_subgraph: digraph with one subgraph!');
    }

    public function test_analysis_subgraph_digraph_with_subgraphs() {
        $digraph = array('digraph "explaining graph" {',
            'tooltip="";',
            'id="explaining_graph";',
            'compound=true;',
            'rankdir = LR;',
            '',
            '"nd7" [shape=box, id="graphid_7", color=purple, style=filled, label="begin", fillcolor=purple,tooltip="begin"];',
            '"nd8" [shape=box, id="graphid_8", color=purple, style=filled, label="end", fillcolor=purple,tooltip="end"];',
            'subgraph "cluster_2_0_3" {style=solid;color=black;bgcolor=white;label="subpattern #1";id="graphid_2_0_3";tooltip="subexpression";',
            'subgraph "cluster_3_1_2" {style=dotted;color=black;bgcolor=white;label="repeated any number of times";id="graphid_3_1_2";tooltip="quantifier";',
            '"nd4_1_1" [shape=ellipse, id="graphid_4_1_1",color=black, style=solid, label="a", fillcolor=white,tooltip="a"];',
            '}',
            '}',
            'subgraph "cluster_5_4_6" {style=solid;color=black;bgcolor=white;label="subpattern #2";id="graphid_5_4_6";tooltip="subexpression";',
            '"nd6_5_5" [shape=ellipse, id="graphid_6_5_5",color=black, style=solid, label="b", fillcolor=white,tooltip="b"];',
            '}',
            '"nd4_1_1" -> "nd6_5_5"[id="graphid_1", label="", arrowhead="normal", color="black", tooltip="concatenation", ]',
            '"nd7" -> "nd4_1_1"[id="graphid_9", label="", arrowhead="normal", color="black", tooltip="", ]',
            '"nd6_5_5" -> "nd8"[id="graphid_10", label="", arrowhead="normal", color="black", tooltip="", ]',
            '}');

        $etalon = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', null, 'graphid_7');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', null, 'graphid_8');
        $etalon->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $etalon->subgraphs[0]->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('repeated any number of times', 'graphid_3_1_2');
        $etalon->subgraphs[0]->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', null, 'graphid_4_1_1');
        $etalon->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #2', 'graphid_5_4_6');
        $etalon->subgraphs[1]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', null, 'graphid_6_5_5');
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->subgraphs[0]->subgraphs[0]->nodes[0], $etalon->subgraphs[1]->nodes[0], $etalon);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->nodes[0], $etalon->subgraphs[0]->subgraphs[0]->nodes[0], $etalon);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->subgraphs[1]->nodes[0], $etalon->nodes[1], $etalon);

        $pos = 0;

        $resultgraph = analysis_subgraph($digraph, $pos);

        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_graphs($resultgraph, $etalon), 'Failed with test_analysis_subgraph: digraph with subgraphs!');
    }

    public function test_add_link_of_graph() {
        $source = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', null, 'graphid_4_1_1');
        $destination = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', null, 'graphid_6_5_5');

        $nodesofgraph['graphid_4_1_1'] = $source;
        $nodesofgraph['graphid_6_5_5'] = $destination;
        $str = '"nd4_1_1" -> "nd6_5_5"[id="graphid_2_0_1", label="a word boundary", arrowhead="normal", color="black", tooltip="a word boundary", ]';

        $resultlinkofgraph = add_link_of_graph($str, $nodesofgraph, null);

        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($source, $resultlinkofgraph->source), 'Failed with test_add_link_of_graph_with_assertion: the resulting node-source of graph is not equal to the reference node-source of graph!');
        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($destination, $resultlinkofgraph->destination), 'Failed with test_add_link_of_graph_with_assertion: the resulting node-destination of graph is not equal to the reference node-destination of graph!');
        $this->assertTrue('a word boundary' == $resultlinkofgraph->label, 'Failed with test_add_link_of_graph_with_assertion: the resulting label of link is not equal to the reference label of link!');

        // -----------------------------------------------------------------------------

        $str = '"nd4_1_1" -> "nd6_5_5"[id="graphid_5", label="", arrowhead="normal", color="black", tooltip="", ]';

        $resultlinkofgraph = add_link_of_graph($str, $nodesofgraph, null);

        $this->assertTrue('' == $resultlinkofgraph->label, 'Failed with test_add_link_of_graph_without_assertion: the resulting label of link is not equal to the reference label of link!');
    }

    public function test_find_subgraph() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('repeated any number of times', 'graphid_3_1_2');
        $graph->subgraphs[0]->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph->subgraphs[0]->subgraphs[0], 'graphid_4_1_1');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #2', 'graphid_5_4_6');
        $graph->subgraphs[1]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[1], 'graphid_6_5_5');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->subgraphs[0]->nodes[0], $graph->subgraphs[1]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->subgraphs[0]->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[1]->nodes[0], $graph->nodes[1], $graph);

        $this->assertTrue(true == find_subgraph($graph, $graph->subgraphs[0]->subgraphs[0]), 'Failed with test_find_subgraph_search_subgraph_is_found: result of the function is incorrect!');

        // -----------------------------------------------------------------------------

        $this->assertTrue(false == find_subgraph($graph->subgraphs[1], $graph->subgraphs[0]->subgraphs[0]), 'Failed with test_find_subgraph_search_subgraph_is_not_found: result of the function is incorrect!');
    }

    public function test_add_label_as_node_finite_quant() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('{$a->firstoperand} repeated from {$a->leftborder} to {$a->rightborder} times{$a->greedy}', 'graphid_3_1_2');
        $graph->style = 'dotted';
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_FINITE_QUANT, 'Failed with test_add_label_as_node_finite_quant test 1: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == '{$a->firstoperand} repeated from {$a->leftborder} to {$a->rightborder} times{$a->greedy}', 'Failed with test_add_label_as_node_finite_quant test 1: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_finite_quant test 1: numberbranchofalter is incorrect!');
        
        // -----------------------------------------------------------------------------

        $graph->label = '{$a->firstoperand} repeated {$a->leftborder} times{$a->greedy}';
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_FINITE_QUANT, 'Failed with test_add_label_as_node_finite_quant test 2: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == '{$a->firstoperand} repeated {$a->leftborder} times{$a->greedy}', 'Failed with test_add_label_as_node_finite_quant test 2: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_finite_quant test 2: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------

        $graph->label = '{$a->firstoperand} repeated no more than {$a->rightborder} times or missing{$a->greedy}';
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_FINITE_QUANT, 'Failed with test_add_label_as_node_finite_quant test 3: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == '{$a->firstoperand} repeated no more than {$a->rightborder} times or missing{$a->greedy}', 'Failed with test_add_label_as_node_finite_quant test 3: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_finite_quant test 3: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------

        $graph->label = '{$a->firstoperand} repeated no more than {$a->rightborder} times{$a->greedy}';
        $tree = new qtype_preg_node_concat;$tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_FINITE_QUANT, 'Failed with test_add_label_as_node_finite_quant test 4: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == '{$a->firstoperand} repeated no more than {$a->rightborder} times{$a->greedy}', 'Failed with test_add_label_as_node_finite_quant test 4: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_finite_quant test 4: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------

        $graph->label = '{$a->firstoperand} may be missing{$a->greedy}';
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_FINITE_QUANT, 'Failed with test_add_label_as_node_finite_quant test 5: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == '{$a->firstoperand} may be missing{$a->greedy}', 'Failed with test_add_label_as_node_finite_quant test 5: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_finite_quant test 5: numberbranchofalter is incorrect!');
    }

    public function test_add_label_as_node_infinite_quant() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('{$a->firstoperand} repeated at least {$a->leftborder} times{$a->greedy}', 'graphid_3_1_2');
        $graph->style = 'dotted';
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_INFINITE_QUANT, 'Failed with test_add_label_as_node_infinite_quant test 1: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == '{$a->firstoperand} repeated at least {$a->leftborder} times{$a->greedy}', 'Failed with test_add_label_as_node_infinite_quant test 1: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_infinite_quant test 1: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------

        $graph->label = '{$a->firstoperand} repeated any number of times or missing{$a->greedy}';
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_INFINITE_QUANT, 'Failed with test_add_label_as_node_infinite_quant test 2: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == '{$a->firstoperand} repeated any number of times or missing{$a->greedy}', 'Failed with test_add_label_as_node_infinite_quant test 2: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_infinite_quant test 2: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------

        $graph->label = '$a->firstoperand} repeated any number of times{$a->greedy}';
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_INFINITE_QUANT, 'Failed with test_add_label_as_node_infinite_quant test 3: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == '$a->firstoperand} repeated any number of times{$a->greedy}', 'Failed with test_add_label_as_node_infinite_quant test 3: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_infinite_quant test 3: numberbranchofalter is incorrect!');
    }

    public function test_add_label_as_node_subexpr() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('subpattern #{$a->number}: [ {$a->firstoperand} ]', 'graphid_3_1_2');
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_SUBEXPR, 'Failed with test_add_label_as_node_subexpr: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == 'subpattern #{$a->number}: [ {$a->firstoperand} ]', 'Failed with test_add_label_as_node_subexpr: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_subexpr: numberbranchofalter is incorrect!');
    }

    public function test_add_label_as_node_explaining_graph_with_subgraph() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('repeated any number of times', 'graphid_1_0_1');
        $graph->subgraphs[0]->style = 'dotted';
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph->subgraphs[0], $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_INFINITE_QUANT, 'Failed with test_add_label_as_node_explaining_graph_with_subgraph: type is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == 'repeated any number of times', 'Failed with test_add_label_as_node_explaining_graph_with_subgraph: subtype is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_explaining_graph_with_subgraph: numberbranchofalter is incorrect!');
    }

    public function test_add_label_as_node_explaining_graph_with_subgraphs() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('repeated any number of times', 'graphid_3_1_2');
        $graph->subgraphs[0]->subgraphs[0]->style = 'dotted';
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #2', 'graphid_5_4_6');
        $tree = new qtype_preg_node_concat;
        $numberbranchofalter = 1;

        add_label_as_node($graph, $graph->subgraphs[0]->subgraphs[0], $tree, $numberbranchofalter);

        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_SUBEXPR, 'Failed with test_add_label_as_node_explaining_graph_with_subgraphs: type 1 is incorrect!');
        $this->assertTrue($tree->operands[0]->subtype == 'subpattern #1', 'Failed with test_add_label_as_node_explaining_graph_with_subgraphs: subtype 1 is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_NODE_INFINITE_QUANT, 'Failed with test_add_label_as_node_explaining_graph_with_subgraphs: type 2 is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[0]->subtype == 'repeated any number of times', 'Failed with test_add_label_as_node_explaining_graph_with_subgraphs: subtype 2 is incorrect!');
        $this->assertTrue($tree->operands[0]->subpattern ==  1, 'Failed with test_add_label_as_node_explaining_graph_with_subgraphs: numberbranchofalter is incorrect!');
    }

    public function test_count_links_for_node_of_graph_links_is_not_found() {
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', null, 'graphid_7');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', null, 'graphid_8');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', null, 'graphid_6_5_5');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', null, 'graphid_6_5_6');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', null, 'graphid_15');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', null, 'graphid_16');
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[0], $nodesofgraph[4], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[4], $nodesofgraph[3], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[4], $nodesofgraph[2], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[3], $nodesofgraph[5], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[2], $nodesofgraph[5], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[5], $nodesofgraph[1], null);

        $resultcount = count_links_for_node_of_graph($nodesofgraph[0], $arraylinks, false);

        $this->assertTrue($resultcount == 0, 'Failed with test_count_links_for_node_of_graph_links_is_not_found: pointing links to a node: result is incorrect');
        
        // -----------------------------------------------------------------------------

        $resultcount = count_links_for_node_of_graph($nodesofgraph[1], $arraylinks, true);

        $this->assertTrue($resultcount == 0, 'Failed with test_count_links_for_node_of_graph_links_is_not_found: links of node: result is incorrect');
    }

    public function test_count_links_for_node_of_graph_links_is_found() {
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', null, 'graphid_7');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', null, 'graphid_8');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', null, 'graphid_6_5_5');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', null, 'graphid_6_5_6');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', null, 'graphid_15');
        $nodesofgraph[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', null, 'graphid_16');
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[0], $nodesofgraph[4], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[4], $nodesofgraph[3], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[4], $nodesofgraph[2], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[3], $nodesofgraph[5], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[2], $nodesofgraph[5], null);
        $arraylinks[] = new qtype_preg_explaining_graph_tool_link('', $nodesofgraph[5], $nodesofgraph[1], null);

        $resultcount = count_links_for_node_of_graph($nodesofgraph[5], $arraylinks, false);

        $this->assertTrue($resultcount == 2, 'Failed with test_count_links_for_node_of_graph_links_is_found: pointing links to a node: result is incorrect');
        
        // -----------------------------------------------------------------------------

        $resultcount = count_links_for_node_of_graph($nodesofgraph[4], $arraylinks, true);

        $this->assertTrue($resultcount == 2, 'Failed with test_count_links_for_node_of_graph_links_is_found: links of node: result is incorrect');
    }

    public function test_take_all_nodes_from_graph_empty_array() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $etalonarray = array();

        $resultarray = take_all_nodes_from_graph($graph);

        $this->assertTrue(count(array_diff_assoc($resultarray, $etalonarray)) == 0, 'Failed with test_take_all_nodes_from_graph_empty_array: resulting array is incorrect');
    }

    public function test_take_all_nodes_from_graph_not_empty_array() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $etalonarray['graphid_7'] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $etalonarray['graphid_8'] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $etalonarray['graphid_6_5_5'] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $etalonarray['graphid_6_5_6'] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $etalonarray['graphid_15'] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $etalonarray['graphid_16'] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');

        $resultarray = take_all_nodes_from_graph($graph);

        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_7'], $etalonarray['graphid_7']), 'Failed with test_take_all_nodes_from_graph_not_empty_array : resulting 0 element is incorrect');
        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_8'], $etalonarray['graphid_8']), 'Failed with test_take_all_nodes_from_graph_not_empty_array : resulting 1 element is incorrect');
        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_6_5_5'], $etalonarray['graphid_6_5_5']), 'Failed with test_take_all_nodes_from_graph_not_empty_array : resulting 2 element is incorrect');
        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_6_5_6'], $etalonarray['graphid_6_5_6']), 'Failed with test_take_all_nodes_from_graph_not_empty_array : resulting 3 element is incorrect');
        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_15'], $etalonarray['graphid_15']), 'Failed with test_take_all_nodes_from_graph_not_empty_array : resulting 4 element is incorrect');
        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_16'], $etalonarray['graphid_16']), 'Failed with test_take_all_nodes_from_graph_not_empty_array : resulting 5 element is incorrect');
    }

    public function test_take_all_nodes_from_graph_many_subgraphs() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('repeated any number of times', 'graphid_3_1_2');
        $graph->subgraphs[0]->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph->subgraphs[0]->subgraphs[0], 'graphid_4_1_1');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #2', 'graphid_5_4_6');
        $graph->subgraphs[1]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[1], 'graphid_6_5_5');
        $etalonarray['graphid_7'] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $etalonarray['graphid_8'] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $etalonarray['graphid_4_1_1'] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph->subgraphs[0]->subgraphs[0], 'graphid_4_1_1');
        $etalonarray['graphid_6_5_5'] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[1], 'graphid_6_5_5');
        
        $resultarray = take_all_nodes_from_graph($graph);

        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_7'], $etalonarray['graphid_7']), 'Failed with test_take_all_nodes_from_graph_subgraphs : resulting 0 element is incorrect');
        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_8'], $etalonarray['graphid_8']), 'Failed with test_take_all_nodes_from_graph_subgraphs : resulting 1 element is incorrect');
        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_4_1_1'], $etalonarray['graphid_4_1_1']), 'Failed with test_take_all_nodes_from_graph_subgraphs : resulting 2 element is incorrect');
        $this->assertTrue(qtype_preg_tool_explaining_graph_test::cmp_nodes($resultarray['graphid_6_5_5'], $etalonarray['graphid_6_5_5']), 'Failed with test_take_all_nodes_from_graph_subgraphs : resulting 3 element is incorrect');
    }

    public function test_take_all_nodes_from_tree_field_operands_does_not_exist() {
        $tree = new qtype_preg_leaf_assert_esc_b(true);
        $tree->id = 'treeid_4_1_1';

        $resultarray = take_all_nodes_from_tree($tree);

        $this->assertTrue($resultarray['treeid_4_1_1']->subtype == qtype_preg_leaf_assert::SUBTYPE_ESC_B, 'Failed with test_take_all_nodes_from_tree_field_operands_does_not_exist: resulting array is incorrect');
    }

    public function test_take_all_nodes_from_tree_many_operands() {
        $tree = new qtype_preg_node_alt;
        $tree->id = 'treeid_4_1_1';
        $tree->operands[] = new qtype_preg_leaf_charset;
        $tree->operands[0]->subtype = 'a';
        $tree->operands[0]->id = 'treeid_5_1_1';
        $tree->operands[] = new qtype_preg_leaf_charset;
        $tree->operands[1]->subtype = 'b';
        $tree->operands[1]->id = 'treeid_6_1_1';

        $resultarray = take_all_nodes_from_tree($tree);

        $this->assertTrue($resultarray['treeid_4_1_1']->subtype == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_take_all_nodes_from_tree_many_operands: 1 tree node: resulting array is incorrect');
        $this->assertTrue($resultarray['treeid_5_1_1']->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_take_all_nodes_from_tree_many_operands: 2 tree node: resulting array is incorrect');
        $this->assertTrue($resultarray['treeid_6_1_1']->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_take_all_nodes_from_tree_many_operands: 3 tree node: resulting array is incorrect');
    }

    public function test_take_all_links_from_graph_empty_array() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');

        $resultarray = take_all_links_from_graph($graph);

        $this->assertTrue(count($resultarray) == 0, 'Failed with test_take_all_links_from_graph_empty_array: resulting array is incorrect');
    }

    public function test_take_all_links_from_graph_not_empty_array() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[5], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[5], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[5], $graph->nodes[1], $graph);
        $etalonarray[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[4], $graph);
        $etalonarray[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[2], $graph);
        $etalonarray[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[3], $graph);
        $etalonarray[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[5], $graph);
        $etalonarray[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[5], $graph);
        $etalonarray[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[5], $graph->nodes[1], $graph);

        $resultarray = take_all_links_from_graph($graph);

        $this->assertTrue(cmp_nodes($resultarray[0]->source, $etalonarray[0]->source), 'Failed with test_take_all_links_from_graph_not_empty_array source 0: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[0]->destination, $etalonarray[0]->destination), 'Failed with test_take_all_links_from_graph_not_empty_array destination 0: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[1]->source, $etalonarray[1]->source), 'Failed with test_take_all_links_from_graph_not_empty_array source 1: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[1]->destination, $etalonarray[1]->destination), 'Failed with test_take_all_links_from_graph_not_empty_array destination 1: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[2]->source, $etalonarray[2]->source), 'Failed with test_take_all_links_from_graph_not_empty_array source 2: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[2]->destination, $etalonarray[2]->destination), 'Failed with test_take_all_links_from_graph_not_empty_array destination 2: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[3]->source, $etalonarray[3]->source), 'Failed with test_take_all_links_from_graph_not_empty_array source 3: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[3]->destination, $etalonarray[3]->destination), 'Failed with test_take_all_links_from_graph_not_empty_array destination 3: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[4]->source, $etalonarray[4]->source), 'Failed with test_take_all_links_from_graph_not_empty_array source 4: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[4]->destination, $etalonarray[4]->destination), 'Failed with test_take_all_links_from_graph_not_empty_array destination 4: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[5]->source, $etalonarray[5]->source), 'Failed with test_take_all_links_from_graph_not_empty_array source 5: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[5]->destination, $etalonarray[5]->destination), 'Failed with test_take_all_links_from_graph_not_empty_array destination 5: resulting array is incorrect');
    }

    public function test_take_all_links_from_graph_many_subgraphs() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('repeated any number of times', 'graphid_3_1_2');
        $graph->subgraphs[0]->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph->subgraphs[0]->subgraphs[0], 'graphid_4_1_1');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #2', 'graphid_5_4_6');
        $graph->subgraphs[1]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[1], 'graphid_6_5_5');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->subgraphs[0]->nodes[0], $graph->subgraphs[1]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->subgraphs[0]->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[1]->nodes[0], $graph->nodes[1], $graph);
        $etalonarray[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->subgraphs[0]->nodes[0], $graph->subgraphs[1]->nodes[0], $graph);
        $etalonarray[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->subgraphs[0]->subgraphs[0]->nodes[0], $graph);
        $etalonarray[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[1]->nodes[0], $graph->nodes[1], $graph);

        $resultarray = take_all_links_from_graph($graph);

        $this->assertTrue(cmp_nodes($resultarray[0]->source, $etalonarray[0]->source), 'Failed with test_take_all_links_from_graph_many_subgraphs source 0: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[0]->destination, $etalonarray[0]->destination), 'Failed with test_take_all_links_from_graph_many_subgraphs destination 0: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[1]->source, $etalonarray[1]->source), 'Failed with test_take_all_links_from_graph_many_subgraphs source 1: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[1]->destination, $etalonarray[1]->destination), 'Failed with test_take_all_links_from_graph_many_subgraphs destination 1: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[2]->source, $etalonarray[2]->source), 'Failed with test_take_all_links_from_graph_many_subgraphs source 2: resulting array is incorrect');
        $this->assertTrue(cmp_nodes($resultarray[2]->destination, $etalonarray[2]->destination), 'Failed with test_take_all_links_from_graph_many_subgraphs destination 2: resulting array is incorrect');
    }

    public function test_add_tree_node_link_with_start_tree_node() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[3], $graph);

        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        
        add_tree_node($graph, $tree, $graph->nodes[2], $altersarray, qtype_preg_node::TYPE_LEAF_CHARSET, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: type is incorrect');
        $this->assertTrue($tree->operands[0]->subtype == 'b', 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_6_5_5', 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: id is incorrect');
        $this->assertTrue(empty($altersarray) == 'true', 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: array with id of alternatives is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------
        
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[5], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        
        add_tree_node($graph, $tree, $graph->nodes[1], $altersarray, qtype_preg_node::TYPE_NODE_ALT, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_add_tree_node_link_with_start_tree_node: node_alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_15', 'Failed with test_add_tree_node_link_with_start_tree_node: node_alt: id is incorrect');
        $this->assertTrue(count($altersarray) == 1, 'Failed with test_add_tree_node_link_with_start_tree_node: node_alt: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_15', 'Failed with test_add_tree_node_link_with_start_tree_node: node_alt: id 0 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_start_tree_node: node_alt: numberbranchofalter is incorrect!');

        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('from a to 100','from 100 to a'), 'record', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[1]->invert = true;
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[3], $graph);

        // -----------------------------------------------------------------------------

        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        
        add_tree_node($graph, $tree, $graph->nodes[1], $altersarray, qtype_preg_node::TYPE_LEAF_CHARSET, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: record: type is incorrect');
        $this->assertTrue($tree->operands[0]->subtype == '[^a-100100-a]', 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: record: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_6_5_6', 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: record: id is incorrect');
        $this->assertTrue(empty($altersarray) == 'true', 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: array with id of alternatives is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_start_tree_node: leaf_charset: numberbranchofalter is incorrect!');
    }
    
    public function test_add_tree_node_link_with_alt_tree_node() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[5], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[] = new qtype_preg_node_alt;
        $tree->operands[0]->id = 'treeid_15';

        $numberbranchofalter = 3;
        
        $altersarray[] = 'treeid_15';
        
        add_tree_node($graph, $tree, $graph->nodes[3], $altersarray, qtype_preg_node::TYPE_LEAF_CHARSET, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 1: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subtype == 'b', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 1: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_6_5_5', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 1: id is incorrect');
        $this->assertTrue(count($altersarray) == 1, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 1: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_15', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 1: id 0 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 1: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------
        
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_19');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[5], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[5], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[5], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[5], $graph->nodes[6], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[] = new qtype_preg_node_alt;
        $tree->operands[0]->id = 'treeid_15';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        $altersarray[] = 'treeid_15';
        
        add_tree_node($graph, $tree, $graph->nodes[2], $altersarray, qtype_preg_node::TYPE_NODE_ALT, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 2: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_19', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 2: id is incorrect');
        $this->assertTrue(count($altersarray) == 2, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 2: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_15', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 2: id 0 of alternative is incorrect');
        $this->assertTrue($altersarray[1] == 'treeid_19', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 2: id 1 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 2: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------
        
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph->subgraphs[0], 'graphid_15');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_6');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_5');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph->subgraphs[0], 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->subgraphs[0]->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->subgraphs[0]->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[1], $graph->subgraphs[0]->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[2], $graph->subgraphs[0]->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[3], $graph->nodes[1], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[] = new qtype_preg_node_subexpr('subpattern #1');
        $tree->operands[0]->id = 'treeid_2_0_3';
        $tree->operands[0]->operands[] = new qtype_preg_node_alt;
        $tree->operands[0]->operands[0]->id = 'treeid_15';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        $altersarray[] = 'treeid_15';
        
        add_tree_node($graph, $tree, $graph->subgraphs[0]->nodes[1], $altersarray, qtype_preg_node::TYPE_LEAF_CHARSET, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 3: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subtype == 'a', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 3: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->id == 'treeid_6_5_6', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 3: id is incorrect');
        $this->assertTrue(count($altersarray) == 1, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 3: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_15', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 3: id 0 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 3: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------
        
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph->subgraphs[0], 'graphid_15');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph->subgraphs[0], 'graphid_19');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_6');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_5');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph->subgraphs[0], 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->subgraphs[0]->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->subgraphs[0]->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[1], $graph->subgraphs[0]->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[1], $graph->subgraphs[0]->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[2], $graph->subgraphs[0]->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[3], $graph->subgraphs[0]->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[4], $graph->nodes[1], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[] = new qtype_preg_node_subexpr('subpattern #1');
        $tree->operands[0]->id = 'treeid_2_0_3';
        $tree->operands[0]->operands[] = new qtype_preg_node_alt;
        $tree->operands[0]->operands[0]->id = 'treeid_15';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        $altersarray[] = 'treeid_15';
        
        add_tree_node($graph, $tree, $graph->subgraphs[0]->nodes[1], $altersarray, qtype_preg_node::TYPE_NODE_ALT, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 4: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->id == 'treeid_19', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 4: id is incorrect');
        $this->assertTrue(count($altersarray) == 2, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 4: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_15', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 4: id 0 of alternative is incorrect');
        $this->assertTrue($altersarray[1] == 'treeid_19', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 4: id 1 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 4: numberbranchofalter is incorrect!');
        
        // -----------------------------------------------------------------------------

        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b-z','1-5'), 'record', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[3]->invert = false;
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[5], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[] = new qtype_preg_node_alt;
        $tree->operands[0]->id = 'treeid_15';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        $altersarray[] = 'treeid_15';
        
        add_tree_node($graph, $tree, $graph->nodes[3], $altersarray, qtype_preg_node::TYPE_LEAF_CHARSET, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 6: record: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subtype == '[b-z1-5]', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 6: record: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_6_5_5', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 6: record: id is incorrect');
        $this->assertTrue(count($altersarray) == 1, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 6: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_15', 'Failed with test_add_tree_node_link_with_alt_tree_node: test 6: id 0 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_alt_tree_node: test 6: numberbranchofalter is incorrect!');
    }
    
    public function test_add_tree_node_link_with_subgraph_tree_node() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->nodes[1], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[] = new qtype_preg_node_subexpr('subpattern #1');
        $tree->operands[0]->id = 'treeid_2_0_3';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        
        add_tree_node($graph, $tree, $graph->subgraphs[0]->nodes[0], $altersarray, qtype_preg_node::TYPE_LEAF_CHARSET, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 1: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subtype == 'a', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 1: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_6_5_6', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 1: id is incorrect');
        $this->assertTrue(count($altersarray) == 0, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 1: array with id of alternatives is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 1: numberbranchofalter is incorrect!');
        
        // -----------------------------------------------------------------------------

        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph->subgraphs[0], 'graphid_19');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_6');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_5');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph->subgraphs[0], 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->subgraphs[0]->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->subgraphs[0]->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[1], $graph->subgraphs[0]->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[2], $graph->subgraphs[0]->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[3], $graph->nodes[1], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[] = new qtype_preg_node_subexpr('subpattern #1');
        $tree->operands[0]->id = 'treeid_2_0_3';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        
        add_tree_node($graph, $tree, $graph->subgraphs[0]->nodes[0], $altersarray, qtype_preg_node::TYPE_NODE_ALT, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 2: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_19', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 2: id is incorrect');
        $this->assertTrue(count($altersarray) == 1,  'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 2: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_19', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 2: id 0 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 2: numberbranchofalter is incorrect!');

        // -----------------------------------------------------------------------------

        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_19');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->nodes[3], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[0] = new qtype_preg_node_alt;
        $tree->operands[0]->id = 'treeid_19';
        $tree->operands[0]->operands[] = new qtype_preg_node_subexpr('subpattern #1');
        $tree->operands[0]->operands[0]->id = 'treeid_2_0_3';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        $altersarray[] = 'treeid_19';
        
        add_tree_node($graph, $tree, $graph->subgraphs[0]->nodes[0], $altersarray, qtype_preg_node::TYPE_LEAF_CHARSET, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 3: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subtype == 'b', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 3: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->id == 'treeid_6_5_5', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 3: id is incorrect');
        $this->assertTrue(count($altersarray) == 1, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 3: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_19', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 3: id 0 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 3: numberbranchofalter is incorrect!');        
        
        // -----------------------------------------------------------------------------

        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_19');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph->subgraphs[0], 'graphid_21');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->subgraphs[0]->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[1], $graph->nodes[3], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[0] = new qtype_preg_node_alt;
        $tree->operands[0]->id = 'treeid_19';
        $tree->operands[0]->operands[] = new qtype_preg_node_subexpr('subpattern #1');
        $tree->operands[0]->operands[0]->id = 'treeid_2_0_3';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        $altersarray[] = 'treeid_19';
        
        add_tree_node($graph, $tree, $graph->subgraphs[0]->nodes[0], $altersarray, qtype_preg_node::TYPE_NODE_ALT, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 4: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->id == 'treeid_21', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 4: id is incorrect');
        $this->assertTrue(count($altersarray) == 2, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 4: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_19', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 4: id 0 of alternative is incorrect');
        $this->assertTrue($altersarray[1] == 'treeid_21', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 4: id 1 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 4: numberbranchofalter is incorrect!');
    
        // -----------------------------------------------------------------------------

        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_19');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b','z-0'), 'record', 'black', $graph->subgraphs[0], 'graphid_6_5_5');
        $graph->subgraphs[0]->nodes[0]->invert = true;
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->nodes[3], $graph);
        
        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_7';
        $tree->operands[0] = new qtype_preg_node_alt;
        $tree->operands[0]->id = 'treeid_19';
        $tree->operands[0]->operands[] = new qtype_preg_node_subexpr('subpattern #1');
        $tree->operands[0]->operands[0]->id = 'treeid_2_0_3';

        $numberbranchofalter = 3;
        
        $altersarray = array();
        $altersarray[] = 'treeid_19';
        
        add_tree_node($graph, $tree, $graph->subgraphs[0]->nodes[0], $altersarray, qtype_preg_node::TYPE_LEAF_CHARSET, $numberbranchofalter);
        
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 5: record: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subtype == '[^bz-0]', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 5: record: tsubtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->id == 'treeid_6_5_5', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 5: record: tid is incorrect');
        $this->assertTrue(count($altersarray) == 1, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 5: array with id of alternatives is incorrect');
        $this->assertTrue($altersarray[0] == 'treeid_19', 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 5: id 0 of alternative is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subpattern ==  3, 'Failed with test_add_tree_node_link_with_subgraph_tree_node: test 5: numberbranchofalter is incorrect!');           
    }

    public function test_analysis_node_of_graph_begin_node() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_1');

        $tree = null;

        $numberbranchofalter = 0;

        analysis_node_of_graph($graph->nodes[0], $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_analysis_node_of_graph_begin_node: type is incorrect');
        $this->assertTrue($tree->id == 'treeid_1', 'Failed with test_analysis_node_of_graph_begin_node: id is incorrect');
        $this->assertTrue($tree->subpattern ==  0, 'Failed with test_analysis_node_of_graph_begin_node: numberbranchofalter is incorrect!');
    }

    public function test_analysis_node_of_graph_end_node() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_2');

        $tree = null;

        $numberbranchofalter = 0;

        analysis_node_of_graph($graph->nodes[0], $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree == null, 'Failed with test_analysis_node_of_graph_end_node: tree is incorrect');
    }

    public function test_analysis_node_of_graph_charset_node() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_1');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_2');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);

        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_1';
        $tree->subpattern = 0;

        $numberbranchofalter = 0;

        analysis_node_of_graph($graph->nodes[1], $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_analysis_node_of_graph_charset_node concat: type is incorrect');
        $this->assertTrue($tree->id == 'treeid_1', 'Failed with test_analysis_node_of_graph_charset_node concat: id is incorrect');
        $this->assertTrue($tree->subpattern == 0, 'Failed with test_analysis_node_of_graph_charset_node concat: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_charset_node charset: type is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_6_5_6', 'Failed with test_analysis_node_of_graph_charset_node charset: id is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern ==  0, 'Failed with test_analysis_node_of_graph_charset_node charset: numberbranchofalter is incorrect!');
    }

    public function test_analysis_node_of_graph_alt_node_with_charsets_without_asserts() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_1');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[5], $graph);

        $tree = new qtype_preg_node_concat;
        $tree->id = 'treeid_1';
        $tree->subpattern = 0;

        $numberbranchofalter = 0;

        analysis_node_of_graph($graph->nodes[0], $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts concat: type is incorrect');
        $this->assertTrue($tree->id == 'treeid_1', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts concat: id is incorrect');
        $this->assertTrue($tree->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts concat: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_15', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts alt: id is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts alt: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_6_5_6', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts charset a: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts charset a: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts charset b: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->id == 'treeid_6_5_5', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts charset b: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->subpattern ==  1, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts charset b: numberbranchofalter is incorrect!');
    }

    public function test_analysis_node_of_graph_alt_node_with_charsets_with_asserts_in_start() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_1');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('a word boundary', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('not a word boundary', $graph->nodes[1], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[5], $graph);

        $numberbranchofalter = 0;

        analysis_node_of_graph($graph->nodes[0], $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start concat: type is incorrect');
        $this->assertTrue($tree->id == 'treeid_1', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start concat: id is incorrect');
        $this->assertTrue($tree->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start concat: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_15', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start alt: id is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start alt: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[0]->subtype == qtype_preg_leaf_assert::SUBTYPE_ESC_B, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start assert \b: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_15_0', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start assert \b: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start assert \b: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->id == 'treeid_6_5_6', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start charset a: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->subpattern ==  0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start charset a: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[2]->subtype == qtype_preg_leaf_assert::SUBTYPE_ESC_B, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start assert \B: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[2]->id == 'treeid_15_1', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start assert \B: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[2]->subpattern ==  1, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start assert \B: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[3]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start charset b: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[3]->id == 'treeid_6_5_5', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start charset b: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[3]->subpattern ==  1, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_start charset b: numberbranchofalter is incorrect!');
    }

    public function test_analysis_node_of_graph_alt_node_with_charsets_with_asserts_in_end() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_1');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6_5_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('a word boundary', $graph->nodes[2], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('not a word boundary', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[5], $graph);

        $numberbranchofalter = 0;

        analysis_node_of_graph($graph->nodes[0], $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end concat: type is incorrect');
        $this->assertTrue($tree->id == 'treeid_1', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end concat: id is incorrect');
        $this->assertTrue($tree->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end concat: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_15', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end alt: id is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end alt: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_6_5_6', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end charset a: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end charset a: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->subtype == qtype_preg_leaf_assert::SUBTYPE_ESC_B, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end assert \b: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->id == 'treeid_6_5_6_0', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end assert \b: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->subpattern ==  0, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end assert \b: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[2]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end charset b: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[2]->id == 'treeid_6_5_5', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end charset b: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[2]->subpattern ==  1, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end charset b: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[3]->subtype == qtype_preg_leaf_assert::SUBTYPE_ESC_B, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end assert \B: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[3]->id == 'treeid_6_5_5_1', 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end assert \B: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[3]->subpattern ==  1, 'Failed with test_analysis_node_of_graph_alt_node_with_charsets_without_asserts_in_end assert \B: numberbranchofalter is incorrect!');
    }

    public function test_analysis_node_of_graph_alt_node_with_nothing() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_1');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);

        $numberbranchofalter = 0;

        analysis_node_of_graph($graph->nodes[0], $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: concat: type is incorrect');
        $this->assertTrue($tree->id == 'treeid_1', 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: concat: id is incorrect');
        $this->assertTrue($tree->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: concat: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_15', 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: alt: id is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: alt: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_6_5_6', 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: charset a: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  0, 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: charset a: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->type == 'leaf_meta', 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: nothing: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->id == 'treeid_15N', 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: nothing: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->subpattern ==  1, 'Failed with test_analysis_node_of_graph_alt_node_with_nothing: nothing: numberbranchofalter is incorrect!');
    }

    public function test_analysis_node_of_graph_alt_node_with_subgraph() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_1');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_15');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_6_5_6');
        $graph->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_2_0_3');
        $graph->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph->subgraphs[0], 'graphid_6_5_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_16');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_8');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->subgraphs[0]->nodes[0], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->subgraphs[0]->nodes[0], $graph->nodes[3], $graph);

        $numberbranchofalter = 0;

        analysis_node_of_graph($graph->nodes[0], $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: concat: type is incorrect');
        $this->assertTrue($tree->id == 'treeid_1', 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: concat: id is incorrect');
        $this->assertTrue($tree->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: concat: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_15', 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: alt: id is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: alt: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_6_5_6', 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: charset a: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  0, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: charset a: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->type == qtype_preg_node::TYPE_NODE_SUBEXPR, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: type of subgraph is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->subtype == 'subpattern #1', 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: subtype of subgraph is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->subpattern ==  1, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: subgraph: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: charset b: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->operands[0]->id == 'treeid_6_5_7', 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: charset b: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->operands[0]->subpattern ==  1, 'Failed with test_analysis_node_of_graph_alt_node_with_subgraph: charset b: numberbranchofalter is incorrect!');
    }

    public function test_analysis_node_of_graph_alt_node_with_alternative() {
        $graph = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $graph, 'graphid_1');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_2');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a'), 'ellipse', 'black', $graph, 'graphid_3');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_5');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $graph, 'graphid_6');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('c'), 'ellipse', 'black', $graph, 'graphid_7');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_8');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $graph, 'graphid_9');
        $graph->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $graph, 'graphid_10');
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[0], $graph->nodes[1], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[2], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[1], $graph->nodes[3], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[2], $graph->nodes[7], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[4], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[3], $graph->nodes[5], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[4], $graph->nodes[6], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[5], $graph->nodes[6], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[6], $graph->nodes[7], $graph);
        $graph->links[] = new qtype_preg_explaining_graph_tool_link('', $graph->nodes[7], $graph->nodes[8], $graph);

        $numberbranchofalter = 0;

        analysis_node_of_graph($graph->nodes[0], $graph, $tree, $numberbranchofalter);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: concat: type is incorrect');
        $this->assertTrue($tree->id == 'treeid_1', 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: concat: id is incorrect');
        $this->assertTrue($tree->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: concat: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->id == 'treeid_2', 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: alt: id is incorrect');
        $this->assertTrue($tree->operands[0]->subpattern == 0, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: alt: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->id == 'treeid_3', 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: charset a: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subpattern ==  0, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: charset a: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: alt 2: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->id == 'treeid_5', 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: alt 2: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->subpattern == 1, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: alt 2: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: charset b: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->operands[0]->id == 'treeid_6', 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: charset b: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->operands[0]->subpattern ==  1, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: charset b: numberbranchofalter is incorrect!');
        $this->assertTrue($tree->operands[0]->operands[1]->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: charset c: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->operands[1]->id == 'treeid_7', 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: charset c: id is incorrect');
        $this->assertTrue($tree->operands[0]->operands[1]->operands[1]->subpattern ==  2, 'Failed with test_analysis_node_of_graph_alt_node_with_alternative: charset c: numberbranchofalter is incorrect!');
    }

    public function test_add_concatenation_for_node_subgraph() {
        $tree = new qtype_preg_node_finite_quant;
        $tree->id = 'treeid_1';
        $tree->operands[] = new qtype_preg_leaf_charset;
        $tree->operands[0]->id = 'treeid_2';
        $tree->operands[] = new qtype_preg_node_alt;
        $tree->operands[1]->id = 'treeid_3';

        $numberbranchofalter = 0;

        $operandsofsubgraph = add_concatenation_for_node($tree, $numberbranchofalter);

        $this->assertTrue($operandsofsubgraph[0]->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_add_concatenation_for_node_subgraph: finite_quant: concat: array is incorrect');
        $this->assertTrue($operandsofsubgraph[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_concatenation_for_node_subgraph: finite_quant: charset: array is incorrect');
        $this->assertTrue($operandsofsubgraph[0]->operands[1]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_add_concatenation_for_node_subgraph: finite_quant: alt: array is incorrect');

        // -----------------------------------------------------------------------------

        $tree = new qtype_preg_node_infinite_quant;
        $tree->id = 'treeid_1';
        $tree->operands[] = new qtype_preg_leaf_charset;
        $tree->operands[0]->id = 'treeid_2';
        $tree->operands[] = new qtype_preg_node_alt;
        $tree->operands[1]->id = 'treeid_3';

        $numberbranchofalter = 0;

        $operandsofsubgraph = add_concatenation_for_node($tree, $numberbranchofalter);

        $this->assertTrue($operandsofsubgraph[0]->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_add_concatenation_for_node_subgraph: infinite_quant: concat: array is incorrect');
        $this->assertTrue($operandsofsubgraph[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_concatenation_for_node_subgraph: infinite_quant: charset: array is incorrect');
        $this->assertTrue($operandsofsubgraph[0]->operands[1]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_add_concatenation_for_node_subgraph: infinite_quant: alt: array is incorrect');

        // -----------------------------------------------------------------------------

        $tree = new qtype_preg_node_subexpr('subpattern #1');
        $tree->id = 'treeid_1';
        $tree->operands[] = new qtype_preg_leaf_charset;
        $tree->operands[0]->id = 'treeid_2';
        $tree->operands[] = new qtype_preg_node_alt;
        $tree->operands[1]->id = 'treeid_3';

        $numberbranchofalter = 0;

        $operandsofsubgraph = add_concatenation_for_node($tree, $numberbranchofalter);

        $this->assertTrue($operandsofsubgraph[0]->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_add_concatenation_for_node_subgraph: subexpr: concat: array is incorrect');
        $this->assertTrue($operandsofsubgraph[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_concatenation_for_node_subgraph: subexpr: charset: array is incorrect');
        $this->assertTrue($operandsofsubgraph[0]->operands[1]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_add_concatenation_for_node_subgraph: subexpr: alt: array is incorrect');
    }

    public function test_add_concatenation_for_node_alt() {
        $tree = new qtype_preg_node_alt;
        $tree->subpattern = 0;
        $tree->id = 'treeid_1';
        $tree->operands[] = new qtype_preg_leaf_charset;
        $tree->operands[0]->subpattern = 0;
        $tree->operands[0]->id = 'treeid_2';
        $tree->operands[] = new qtype_preg_node_alt;
        $tree->operands[1]->subpattern = 1;
        $tree->operands[1]->id = 'treeid_3';
        $tree->operands[] = new qtype_preg_leaf_charset;
        $tree->operands[2]->subpattern = 1;
        $tree->operands[2]->id = 'treeid_4';

        $numberbranchofalter = 2;

        $operandsofalt = add_concatenation_for_node($tree, $numberbranchofalter);

        $this->assertTrue($operandsofalt[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_concatenation_for_node_alt charset: array is incorrect');
        $this->assertTrue($operandsofalt[1]->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_add_concatenation_for_node_alt concat: array is incorrect');
        $this->assertTrue($operandsofalt[1]->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_add_concatenation_for_node_alt alt: array is incorrect');
        $this->assertTrue($operandsofalt[1]->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_add_concatenation_for_node_alt charset 2: array is incorrect');
    }

    public function test_add_concatenation_for_node_not_alt_not_subgraph() {
        $tree = new qtype_preg_leaf_charset();

        $numberbranchofalter = 2;

        $operands = add_concatenation_for_node($tree, $numberbranchofalter);

        $this->assertTrue($operands == null, 'Failed with test_add_concatenation_for_node_not_alt_not_subgraph: array is incorrect');
    }

    public function test_split_node_with_word() {
        $splitnode = new qtype_preg_leaf_charset();
        $splitnode->subtype = 'word';
        $splitnode->id = 'treeid_1';
        $splitnode->subpattern = 0;

        $newnode = split_node_with_word($splitnode);

        $this->assertTrue($newnode->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_split_node_with_word concat type: newnode is incorrect');
        $this->assertTrue($newnode->id == 'treeid_1', 'Failed with test_split_node_with_word concat id: newnode is incorrect');
        $this->assertTrue($newnode->subpattern == 0, 'Failed with test_split_node_with_word concat numberbranchofalter: newnode is incorrect');
        $this->assertTrue($newnode->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_split_node_with_word charset w type: newnode is incorrect');
        $this->assertTrue($newnode->operands[0]->subtype == 'w', 'Failed with test_split_node_with_word charset w subtype: newnode is incorrect');
        $this->assertTrue($newnode->operands[0]->id == 'treeid_1_0', 'Failed with test_split_node_with_word charset w id: newnode is incorrect');
        $this->assertTrue($newnode->operands[0]->subpattern == 0, 'Failed with test_split_node_with_word charset w numberbranchofalter: newnode is incorrect');
        $this->assertTrue($newnode->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_split_node_with_word charset o type: newnode is incorrect');
        $this->assertTrue($newnode->operands[1]->subtype == 'o', 'Failed with test_split_node_with_word charset o subtype: newnode is incorrect');
        $this->assertTrue($newnode->operands[1]->id == 'treeid_1_1', 'Failed with test_split_node_with_word charset o id: newnode is incorrect');
        $this->assertTrue($newnode->operands[1]->subpattern == 0, 'Failed with test_split_node_with_word charset o numberbranchofalter: newnode is incorrect');
        $this->assertTrue($newnode->operands[2]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_split_node_with_word charset r type: newnode is incorrect');
        $this->assertTrue($newnode->operands[2]->subtype == 'r', 'Failed with test_split_node_with_word charset r subtype: newnode is incorrect');
        $this->assertTrue($newnode->operands[2]->id == 'treeid_1_2', 'Failed with test_split_node_with_word charset r id: newnode is incorrect');
        $this->assertTrue($newnode->operands[2]->subpattern == 0, 'Failed with test_split_node_with_word charset r numberbranchofalter: newnode is incorrect');
        $this->assertTrue($newnode->operands[3]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_split_node_with_word charset d type: newnode is incorrect');
        $this->assertTrue($newnode->operands[3]->subtype == 'd', 'Failed with test_split_node_with_word charset d subtype: newnode is incorrect');
        $this->assertTrue($newnode->operands[3]->id == 'treeid_1_3', 'Failed with test_split_node_with_word charset d id: newnode is incorrect');
        $this->assertTrue($newnode->operands[3]->subpattern == 0, 'Failed with test_split_node_with_word charset d numberbranchofalter: newnode is incorrect');

        // -----------------------------------------------------------------------------

        $splitnode = new qtype_preg_leaf_charset();
        $splitnode->subtype = 'w';
        $splitnode->id = 'treeid_1';
        $splitnode->subpattern = 0;

        $newnode = split_node_with_word($splitnode);

        $this->assertTrue($newnode == null, 'Failed with test_split_node_with_word null: newnode is incorrect');
    }

    public function test_graph_name_to_tree_name() {
        $graphname = 'repeated any number of times or missing';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '*', 'Failed with test_graph_name_to_tree_name repeated any number of times or missing: treename is incorrect');

        // -----------------------------------------------------------------------------

        $graphname = 'repeated any number of times';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '+', 'Failed with test_graph_name_to_tree_name repeated any number of times: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'may be missing';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '?', 'Failed with test_graph_name_to_tree_name may be missing: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'repeated 5 times';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '{5}', 'Failed with test_graph_name_to_tree_name repeated 5 times: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'repeated at least 5 times';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '{5,}', 'Failed with test_graph_name_to_tree_name repeated at least 5 times: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'repeated from 5 to 10 times';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '{5,10}', 'Failed with test_graph_name_to_tree_name repeated from 5 to 10 times: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'node_alt';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '|', 'Failed with test_graph_name_to_tree_name node alt: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'subpattern #5';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '(...)#5', 'Failed with test_graph_name_to_tree_name subpattern: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'a decimal digit';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\d', 'Failed with test_graph_name_to_tree_name a decimal digit: treename is incorrect');

        // -----------------------------------------------------------------------------

        $graphname = 'not a decimal digit';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\D', 'Failed with test_graph_name_to_tree_name not a decimal digit: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'a word character';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\w', 'Failed with test_graph_name_to_tree_name a word character: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'not a word character';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\W', 'Failed with test_graph_name_to_tree_name not a word character: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'a white space';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\s', 'Failed with test_graph_name_to_tree_name a white space: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'not a white space';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\S', 'Failed with test_graph_name_to_tree_name repeated not a white space: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'any character';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '.', 'Failed with test_graph_name_to_tree_name any character: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'line feed(LF)';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\n', 'Failed with test_graph_name_to_tree_name line feed(LF): treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'carriage return character(CR)';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\r', 'Failed with test_graph_name_to_tree_name carriage return character(CR): treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'tabulation(HT)';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\t', 'Failed with test_graph_name_to_tree_name tabulation(HT): treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'a vertical white space character';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\v', 'Failed with test_graph_name_to_tree_name a vertical white space character: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'null character(nul)';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '\\0', 'Failed with test_graph_name_to_tree_name null character(nul): treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'from avi to zii';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == 'avi-zii', 'Failed with test_graph_name_to_tree_name from a to z: treename is incorrect');

        // -----------------------------------------------------------------------------
        
        $graphname = 'from 100 to 2014';

        $treename = graph_name_to_tree_name($graphname);

        $this->assertTrue($treename == '100-2014', 'Failed with test_graph_name_to_tree_name from 0 to 9: treename is incorrect');
    }

        public function test_create_tree_consecutive_characters() {
        $tool = new qtype_preg_explaining_graph_tool('abc');
        $graph = $tool->create_graph();

        $tree = create_tree($graph);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_create_tree_consecutive_characters concat: type is incorrect');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_consecutive_characters charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->subtype == 'a', 'Failed with test_create_tree_consecutive_characters charset a: subtype is incorrect');
        $this->assertTrue($tree->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_consecutive_characters charset b: type is incorrect');
        $this->assertTrue($tree->operands[1]->subtype == 'b', 'Failed with test_create_tree_consecutive_characters charset b: subtype is incorrect');
        $this->assertTrue($tree->operands[2]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_consecutive_characters charset c: type is incorrect');
        $this->assertTrue($tree->operands[2]->subtype == 'c', 'Failed with test_create_tree_consecutive_characters charset c: subtype is incorrect');
    }

    public function test_create_tree_simple_alt() {
        $tool = new qtype_preg_explaining_graph_tool('a|b');
        $graph = $tool->create_graph();

        $tree = create_tree($graph);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_create_tree_simple_alt alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_simple_alt charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->subtype == 'a', 'Failed with test_create_tree_simple_alt charset a: subtype is incorrect');
        $this->assertTrue($tree->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_simple_alt charset b: type is incorrect');
        $this->assertTrue($tree->operands[1]->subtype == 'b', 'Failed with test_create_tree_simple_alt charset b: subtype is incorrect');
    }

    public function test_create_tree_simple_alt_with_nothing() {
        $tool = new qtype_preg_explaining_graph_tool('|b');
        $graph = $tool->create_graph();

        $tree = create_tree($graph);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_create_tree_simple_alt_with_nothing alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_LEAF_META, 'Failed with test_create_tree_simple_alt_with_nothing nothing: type is incorrect');
        $this->assertTrue($tree->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_simple_alt_with_nothing charset b: type is incorrect');
        $this->assertTrue($tree->operands[1]->subtype == 'b', 'Failed with test_create_tree_simple_alt_with_nothing charset b: subtype is incorrect');
    }

    public function test_create_tree_subpat_quant() {
        $tool = new qtype_preg_explaining_graph_tool('(abcd)+');
        $graph = $tool->create_graph();

        $tree = create_tree($graph);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_INFINITE_QUANT, 'Failed with test_create_tree_subpat_quant quant: type is incorrect');
        $this->assertTrue($tree->subtype == '+', 'Failed with test_create_tree_subpat_quant quant: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_SUBEXPR, 'Failed with test_create_tree_subpat_quant subexpr: type is incorrect');
        $this->assertTrue($tree->operands[0]->subtype == '(...)#1', 'Failed with test_create_tree_subpat_quant subexpr: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_create_tree_subpat_quant concat: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_subpat_quant charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subtype == 'a', 'Failed with test_create_tree_subpat_quant charset a: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_subpat_quant charset b: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[1]->subtype == 'b', 'Failed with test_create_tree_subpat_quant charset b: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[2]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_subpat_quant charset c: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[2]->subtype == 'c', 'Failed with test_create_tree_subpat_quant charset c: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[3]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_subpat_quant charset d: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[3]->subtype == 'd', 'Failed with test_create_tree_subpat_quant charset d: subtype is incorrect');
    }

    public function test_create_tree_two_anchors() {
        $tool = new qtype_preg_explaining_graph_tool('^a$');
        $graph = $tool->create_graph();

        $tree = create_tree($graph);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_create_tree_two_anchors concat: type is incorrect');
        $this->assertTrue($tree->operands[0]->subtype == qtype_preg_leaf_assert::SUBTYPE_CIRCUMFLEX, 'Failed with test_create_tree_two_anchors ^: type is incorrect');
        $this->assertTrue($tree->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_two_anchors charset a: type is incorrect');
        $this->assertTrue($tree->operands[1]->subtype == 'a', 'Failed with test_create_tree_two_anchors charset a: subtype is incorrect');
        $this->assertTrue($tree->operands[2]->subtype == qtype_preg_leaf_assert::SUBTYPE_DOLLAR, 'Failed with test_create_tree_two_anchors $: type is incorrect');
    }

    public function test_create_tree_alternative_to_alternative() {
        $tool = new qtype_preg_explaining_graph_tool('a|b(c|d)');
        $graph = $tool->create_graph();

        $tree = create_tree($graph);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_create_tree_alternative_to_alternative alt: type is incorrect');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_alternative_to_alternative charset a: type is incorrect');
        $this->assertTrue($tree->operands[0]->subtype == 'a', 'Failed with test_create_tree_alternative_to_alternative charset a: subtype is incorrect');
        $this->assertTrue($tree->operands[1]->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_create_tree_alternative_to_alternative concat: type is incorrect');
        $this->assertTrue($tree->operands[1]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_alternative_to_alternative charset b: type is incorrect');
        $this->assertTrue($tree->operands[1]->operands[0]->subtype == 'b', 'Failed with test_create_tree_alternative_to_alternative charset b: subtype is incorrect');
        $this->assertTrue($tree->operands[1]->operands[1]->type == qtype_preg_node::TYPE_NODE_SUBEXPR, 'Failed with test_create_tree_alternative_to_alternative subexpr: type is incorrect');
        $this->assertTrue($tree->operands[1]->operands[1]->subtype == '(...)#1', 'Failed with test_create_tree_alternative_to_alternative subexpr: subtype is incorrect');
        $this->assertTrue($tree->operands[1]->operands[1]->operands[0]->type == qtype_preg_node::TYPE_NODE_ALT, 'Failed with test_create_tree_alternative_to_alternative alt 2: type is incorrect');
        $this->assertTrue($tree->operands[1]->operands[1]->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_alternative_to_alternative charset c: type is incorrect');
        $this->assertTrue($tree->operands[1]->operands[1]->operands[0]->operands[0]->subtype == 'c', 'Failed with test_create_tree_alternative_to_alternative charset c: type is incorrect');
        $this->assertTrue($tree->operands[1]->operands[1]->operands[0]->operands[1]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_alternative_to_alternative charset d: type is incorrect');
        $this->assertTrue($tree->operands[1]->operands[1]->operands[0]->operands[1]->subtype == 'd', 'Failed with test_create_tree_alternative_to_alternative charset d: type is incorrect');
    }

    public function test_create_tree_concat_with_charset_and_subexpr() {
        $tool = new qtype_preg_explaining_graph_tool('b(\s)');
        $graph = $tool->create_graph();

        $tree = create_tree($graph);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_CONCAT, 'Failed with test_create_tree_concat_with_charset_and_subexpr concat: type is incorrect');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_concat_with_charset_and_subexpr charset b: type is incorrect');
        $this->assertTrue($tree->operands[0]->subtype == 'b', 'Failed with test_create_tree_concat_with_charset_and_subexpr charset b: subtype is incorrect');
        $this->assertTrue($tree->operands[1]->type == qtype_preg_node::TYPE_NODE_SUBEXPR, 'Failed with test_create_tree_concat_with_charset_and_subexpr subexpr: type is incorrect');
        $this->assertTrue($tree->operands[1]->subtype == '(...)#1', 'Failed with test_create_tree_concat_with_charset_and_subexpr subexpr: subtype is incorrect');
        $this->assertTrue($tree->operands[1]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_alternative_to_alternative charset \s: type is incorrect');
        $this->assertTrue($tree->operands[1]->operands[0]->subtype == '\s', 'Failed with test_create_tree_alternative_to_alternative charset \s: type is incorrect');
    }

    public function test_create_tree_consecutive_subgraphs() {
        $tool = new qtype_preg_explaining_graph_tool('((\w)+){3,}');
        $graph = $tool->create_graph();

        $tree = create_tree($graph);

        $this->assertTrue($tree->type == qtype_preg_node::TYPE_NODE_INFINITE_QUANT, 'Failed with test_create_tree_consecutive_subgraphs quant: type is incorrect');
        $this->assertTrue($tree->subtype == '{3,}', 'Failed with test_create_tree_consecutive_subgraphs quant: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->type == qtype_preg_node::TYPE_NODE_SUBEXPR, 'Failed with test_create_tree_consecutive_subgraphs subexpr 1: type is incorrect');
        $this->assertTrue($tree->operands[0]->subtype == '(...)#1', 'Failed with test_create_tree_consecutive_subgraphs subexpr 1: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->type == qtype_preg_node::TYPE_NODE_INFINITE_QUANT, 'Failed with test_create_tree_consecutive_subgraphs quant 2: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->subtype == '+', 'Failed with test_create_tree_consecutive_subgraphs quant 2: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->type == qtype_preg_node::TYPE_NODE_SUBEXPR, 'Failed with ttest_create_tree_consecutive_subgraphs subexpr 2: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->subtype == '(...)#2', 'Failed with test_create_tree_consecutive_subgraphs subexpr 2: subtype is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->operands[0]->type == qtype_preg_node::TYPE_LEAF_CHARSET, 'Failed with test_create_tree_consecutive_subgraphs charset \w: type is incorrect');
        $this->assertTrue($tree->operands[0]->operands[0]->operands[0]->operands[0]->subtype == '\w', 'Failed with test_create_tree_consecutive_subgraphs charset \w: subtype is incorrect');
    }

    public function test_create_tree() {
        /*
        $tool = new qtype_preg_explaining_graph_tool('^a$b\bc\Bd');
        $graph = $tool->create_graph();
        */

        $etalon = new qtype_preg_explaining_graph_tool_subgraph('', 'explaining_graph');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('not a word character'), 'ellipse', 'hotpink', $etalon, 'graphid_10_15_16');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $etalon, 'graphid_11');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $etalon, 'graphid_12');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('begin'), 'box', 'purple', $etalon, 'graphid_13');
        $etalon->nodes[] = new qtype_preg_explaining_graph_tool_node(array('end'), 'box', 'purple', $etalon, 'graphid_14');
        $etalon->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('repeated no more than 3 times', 'graphid_2_0_13');
        $etalon->subgraphs[0]->style = 'dotted';
        $etalon->subgraphs[0]->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #1', 'graphid_3_0_8');
        $etalon->subgraphs[0]->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('a white space'), 'ellipse', 'hotpink', $etalon->subgraphs[0]->subgraphs[0], 'graphid_5_1_2');
        $etalon->subgraphs[0]->subgraphs[0]->subgraphs[] = new qtype_preg_explaining_graph_tool_subgraph('subpattern #2', 'graphid_6_3_7');
        $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('abc'), 'ellipse', 'black', $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0], 'graphid_8_4_4');
        $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array('b'), 'ellipse', 'black', $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0], 'graphid_9_6_6');
        $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0], 'graphid_21');
        $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[] = new qtype_preg_explaining_graph_tool_node(array(''), 'point', 'black', $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0], 'graphid_22');
        $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[2], $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[0], $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]);
        $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[2], $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[1], $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]);
        $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[0], $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[3], $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]);
        $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[1], $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[3], $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]);
        $etalon->subgraphs[0]->subgraphs[0]->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->subgraphs[0]->subgraphs[0]->nodes[0], $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[2], $etalon->subgraphs[0]->subgraphs[0]);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('not a word boundary', $etalon->nodes[1], $etalon->subgraphs[0]->subgraphs[0]->nodes[0], $etalon);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->nodes[1], $etalon->nodes[0], $etalon);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->nodes[0], $etalon->nodes[2], $etalon);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->nodes[3], $etalon->nodes[1], $etalon);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->nodes[2], $etalon->nodes[4], $etalon);
        $etalon->links[] = new qtype_preg_explaining_graph_tool_link('', $etalon->subgraphs[0]->subgraphs[0]->subgraphs[0]->nodes[3], $etalon->nodes[2], $etalon);

        $tree = create_tree($etalon);

        print("\n");
        print_tree($tree);
    }
}  
?>